export {};

//  在es6中类都是通过class进行声明
// 类可以通过new 创建实例， 类在ts中可以描述类型， 可以标识值，类类型用于描述实例

class Circle {
  x: number; // 类型声明 默认添加public关键字 用来标识此属性是公开的
  y!: number;
  public c!: number;
  constructor(x: number, y: number, c: number) {
    this.x = x;
    // this.y = y;
  }
}

// public 的简写
let c = new Circle(1, 2, 3);
console.log(c); // 1,2,3
class Circle1 {
  constructor(public x: number, public y: number, public c: number) {}
}

let c1 = new Circle1(1, 2, 3);
console.log(c1); // 1,2,3

// 属性修饰符

class Animal {
  // public name: string; // 公开
  public readonly name: string; // 公开 只读 只允许在初始化时被赋值
  // protected name: string; //仅自己和 子类可以访问
  // private name: string; // 仅自己可以访问
  protected constructor(name: string) {
    this.name = name;
  }

  public eat() {
    // 默认public  原型方法  所有字类和实例都可以调用
  }

  static drink() {
    // static   静态方法 只能通过类来调用
  }
  repeat(val: string) {}
}

Animal.drink;
// let an = new Animal("");
// an.drink();
// Animal.age = '我是外部声明的静态属性'  静态属性

// new Animal()  constructor为protected 无法被new
// class Cat extends Animal { constructor 为 private 无法被继承
//--------static 静态类的实现
// Cat.__proto__ = Animal
// Cat.prototype = Object.create(Animal)
class Cat extends Animal {
  // extends 继承原型的属性和方法（包括被static声明的静态方法）
  outProps!: string;
  constructor(name: string, age: number) {
    super(name); // 相当于Animal.call(this)
    console.log(this.name);
  }
  cDrink() {
    // this.name = 1 error
    Cat.drink();
  }
  // type = {}; // 为实例上添加type属性
  get type() {
    // 在原型上 为原型添加原型属性
    return "我是原型内部声明的原型方法";
  }
  static syn = "我是静态属性";
  repeat(val: string) {
    // 由于重载父类  可以在字类中通过super调用repeat方法
    super.repeat(val);
  }

  static drink() {
    // super在静态方法中调用 super=== Animal
    super.drink();
  }
}

// Cat.outProps = "我时外部声明的静态属性";
let cat = new Cat("Tom1", 1);
let cat1 = new Cat("Tom1", 2);
cat.name;
cat.eat();
cat.type;

Cat.syn;
// cat.syn

console.log(cat.type === cat1.type);
// cat.drink()  error

// 实例属性（每个实例都会添加一个）
//  原型属性 （多个实例之间共享）
//  静态属性和方法  （通过类直接访问）

//  属性访问器  （defineProperty）
// 属性访问器场景   通过暴露一个公有属性 去访问一个私有属性 相当与代理
class Ref {
  constructor(private _value: string) {}
  get value() {
    return this._value;
  }
  set value(newValue) {
    this._value = newValue;
  }
}

let r = new Ref("123");
console.log(r.value); // 123

// 子类 父类 有共同方法时  字类方法会重写父类方法  参数类型需要一致 super === 父类的.prototype

// 子类重载父类时  方法的返回值类型需要一致    或者父类定义的返回类型为void  表示对返回参数不关心

const fn: () => void = (): string => "";
